<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Cache-Control" content="no-siteapp">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=1, minimum-scale=1, maximum-scale=1">
<meta name="referrer" content="never">
<meta name="robots" content="index,follow">
<link rel="shortcut icon" href="/favicon.png?v=198964">
<link rel="apple-itouch-icon" href="/favicon.png?v=198964">
<link href="/bundle/index.min.css" rel="stylesheet">
<link href="https://fonts.loli.net/css?family=Merriweather:300,700,700italic,300italic|Open+Sans:700,400" rel="stylesheet">
<link href="https://cdn.staticfile.org/prism/1.16.0/themes/prism.min.css" rel="stylesheet">
<link href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script>
    function ensureDate(e){return"object"!=typeof e&&(e=new Date(e)),e}function dateFormat(e,t){void 0===t&&(t=e,e=ensureDate());let n={M:(e=ensureDate(e)).getMonth()+1,d:e.getDate(),h:e.getHours(),m:e.getMinutes(),s:e.getSeconds(),q:Math.floor((e.getMonth()+3)/3),S:e.getMilliseconds()},r=new RegExp("([yMdhmsqS])+","g");return t=t.replace(r,function(t,r){let u=n[r];if(void 0!==u)return t.length>1&&(u=(u="0"+u).substring(u.length-2)),u;if("y"===r){return(e.getFullYear()+"").substring(4-t.length)}return t})}
</script>
    <meta name="keywords" content="Vuex 学习总结,Vue,Vuex,">
    <meta name="description" content="Vuex 学习总结,Vue,Vuex,">
    <meta name="author" content="江矿先森.">
    <title>Vuex 学习总结</title>
    <link href="/bundle/iconfont.css" rel="stylesheet">
    <link href="/bundle/reward.css" rel="stylesheet">
    <script src='/bundle/av.min.js'></script>
    <script src='/bundle/valine.min.js'></script>
</head>

<body>
    <article class="container">
        <header class="header-wrap asset">
    <nav class="main-nav">
        <ul class="menu vertical naive">
            <li class="menu-item"><a href="/">Home</a></li>
            <li class="menu-item"><a href="/archive.html">Archive</a></li>
            <li class="menu-item"><a href="/tag.html">Tag</a></li>
            
            <li class="menu-item"><a href="/atom.xml">RSS</a></li>
        </ul>
    </nav>
    <div class="bgs" style="background-image: url(https://pic6.58cdn.com.cn/nowater/webim/big/n_v212fe49b1d6d5492cb1def84eeff4b142.jpg);"></div>
    <div class="vertical">
        <div class="header-wrap-content inner">
            <h3 class="title">Stay before every beautiful thoughts.</h3>
            <h3 class="subtitle">Just be nice, always think twice!</h3>
        </div>
    </div>
</header>
        <article class="main article">
            <h1 class="title">Vuex 学习总结</h1>
            <section class="info">
                <span class="avatar" style="background-image: url(https://pic1.58cdn.com.cn/nowater/webim/big/n_v2a9773b605e754c8493cf53ca8f5c0d7e.jpg);"></span> <a class="name" href="javascript:;">江矿先森.</a> 
                <span class="date"><script>document.write(dateFormat( 1505100234 *1000, 'yyyy-MM-dd'))</script></span> 
                <span class="tags"><a class="tages" href="/tag/Vue/index.html">Vue</a><a class="tages" href="/tag/Vuex/index.html">Vuex</a></span>
            </section>
            <article class="content"><p>对于很多新手来说，只是阅读文档是不好消化，我的建议是看看 vuex 的实例，通过研究实例来学习vuex。这样就会好理解多了。如果还是不能理解，最好办法就是先把store 的四个属性：state， getters, mutations, actions 记下来，然后再分析四个属性的特点，什么地方会用到，是怎样连接在一起的？通过这样问自己问题来进行学习。</p>

<p>简单来说，vuex 就是使用一个 store 对象来包含所有的应用层级状态，也就是数据的来源。当然如果应用比较庞大，我们可以将 store 模块化，也就是每个模块都有自己的 store。一个 store 有四个属性：state, getters, mutations, actions。</p>

<h4>1、State</h4>

<p>state 上存放的，说的简单一些就是变量，也就是所谓的状态。没有使用 state 的时候，我们都是直接在 data 中进行初始化的，但是有了 state 之后，我们就把 data 上的数据转移到 state 上去了。当一个组件需要获取多个状态时候，将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题，我们可以使用 mapState 辅助函数帮助我们生成计算属性，让你少按几次键：</p>

<p>其实就是把 state 上保存的变量转移到计算属性上。当映射的计算属性的名称与 state 的子节点名称相同时，我们也可以给 mapState 传一个字符串数组。</p>

<pre><code class="language-js">computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])
</code></pre>

<p>为了更好地理解这个函数的作用，我们可以看看它的源代码。
可以看到，mapstate 即可以接受对象，也可以接受数组。最终返回的是一个对象。并且 res[key] 的值都是来于 store 里的，红色那条代码就是。这样就把两个不相关的属性连接起来了,这也是映射。其他几个辅助函数也是类似的。</p>

<h4>2、Getters</h4>

<p>getters上简单来说就是存放一些公共函数供组件调用。getters 会暴露为 store.getters 对象，也就是说可以通过 store .getters[属性]来进行相应的调用。mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性，其实也就是从 getters 中获取对应的属性，跟解构类似。具体如下图这样我们就可以将 getters 中的 evenOrOdd 属性值传给对应组件中的 evenOrOdd 上。Getters 接受 state 作为其第一个参数，Getters 也可以接受其他 getters 作为第二个参数。</p>

<h4>3、Mutations</h4>

<p>mutations 与事件类似，更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。所以 mutations 上存放的一般就是我们要改变 state 的一些方法。</p>

<pre><code class="language-js">const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})
</code></pre>

<p>我们不能直接调用一个 mutation handler。 这个选项更像是事件注册 ：“当触发一个类型为 increment 的 mutation 时，调用此函数 。”要唤醒一个 mutation handler，你需要以相应的 type 调用 store.commit 方法：</p>

<pre><code class="language-js">store.commit('increment')
</code></pre>

<p>当 mutation 事件类型比较多的时候，我们可以使用常量替代 mutation 事件类型。同时把这些常量放在单独的文件中可以让我们的代码合作者对整个 app 包含的 mutation 一目了然：
一条重要的原则就是要记住 mutation 必须是同步函数 。</p>

<h4>4、Actions</h4>

<p>前面说了， mutation 像事件注册，需要相应的触发条件。而 Action 就那个管理触发条件的。
Action 类似于 mutation，不同在于：Action 提交的是 mutation，而不是直接变更状态。Action 可以包含任意异步操作。</p>

<pre><code class="language-js">actions: {
    increment (context) {
      context.commit('increment')
    }
  }
</code></pre>

<p>Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象，因此你可以调用 context.commit 提交一个 mutation，或者通过 context.state 和 context.getters 来获取 state 和 getters。</p>

<p>实践中，我们会经常会用到 ES2015 的 参数解构 来简化代码（特别是我们需要调用 commit 很多次的时候）</p>

<pre><code class="language-js">actions: {
  increment ({ commit }) {
    commit('increment')
  }
}
</code></pre>

<p>还记得我们前面说过 mutation 像事件类型吗？因此需要我们给定某个动作来进行触发。而这就是分发 action。Action 通过 store.dispatch 方法触发：</p>

<pre><code class="language-js">store.dispatch('increment')
</code></pre>

<p>此外，我们还可以在我们可以在 action 内部执行 异步 操作：</p>

<pre><code class="language-js">actions: {
  incrementAsync ({ commit }) {
    setTimeout(() =&gt; {
      commit('increment')
    }, 1000)
  }
}
</code></pre>

<p>你在组件中使用<code>this.$store.dispatch('xxx')</code> 分发 action，或者使用<code>mapActions</code>辅助函数将组件的 methods 映射为<code>store.dispatch</code>调用（需要先在根节点注入 store ）：</p>

<pre><code class="language-js">import { mapActions } from 'vuex'
export default {
  // ...
  methods: {
    ...mapActions([
      'increment' // 映射 this.increment() 为 this.$store.dispatch('increment')
    ]),
    ...mapActions({
      add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment')
    })
  }
}
</code></pre>

<p>这句话意思其实是，当你使用了 <code>mapActions</code>， 你就不需要再次使用 <code>this.$store.dispatch('xxx')</code>，当你没使用的话，你可以需要手动去分法。
什么时候用大家要根据情况而定的。</p>
</article>
            <section class="author">
                
                <div class="avatar" style="background-image: url(https://pic1.58cdn.com.cn/nowater/webim/big/n_v2a9773b605e754c8493cf53ca8f5c0d7e.jpg);"></div>
                <a class="name" href="javascript:;">江矿先森.</a>
                <div class="intro">前(台)端(菜), 喜欢瞎折腾新技术. 乜野都识少少, 先可以扮代表.</div>
            </section>
            <section class="social">
                <a href="https://github.com/joname1" target="_blank">
                    <i class="iconfont i-github"></i>
                </a>
                <a href="javascript:alert('你电脑中了不知名的病毒, 并抛出了警告 atob(“d3hJZDogam9uYW1lLmxpYW5ndGFu”)')" target="_blank">
                    <i class="iconfont i-wechat"></i>
                </a>
                <a href="https://www.zhihu.com/people/joname-liangtan" target="_blank">
                    <i class="iconfont i-zhihu"></i>
                </a>
                <a href="javascript:alert('对方不想跟你讲话, 并向你扔来一段乱码 atob(“am9uYW1lLmxpYW5ndGFuQGdtYWlsLmNvbQ”)')" target="_blank">
                    <i class="iconfont i-email"></i>
                </a>
            </section>

            <div class="reward">
                <div class="reward-button">赏
                    <span class="reward-code">
                        <span class="alipay-code">
                            <img class="alipay-img wdp-appear" src="https://pic1.58cdn.com.cn/nowater/webim/big/n_v24d5eae197a764eb194b61e366ff263ba.jpg"><b>支付宝扫码</b>
                        </span>
                    <span class="wechat-code">
                            <img class="wechat-img wdp-appear" src="https://pic1.58cdn.com.cn/nowater/webim/big/n_v20ec7ae162f6a4219b8d0b429a2dbc9b3.jpg"><b>微信扫码</b>
                        </span>
                    </span>
                </div>
                
                <p class="reward-notice">如果文章对你有帮助, 扫上方二维码请我喝杯奶茶吧 :p</p>
            </div>

            <div id="comment"></div>
            
        </article>
    </article>
    <footer class="footer clearfix">
    <span class="copyright">
        <script>
            document.write(new Date().getFullYear());
        </script> <i class="fa fa-copyright"></i> Made with <i class="fa fa-heart"></i> using &ltjoname /&gt
        <span id="runtime_span"></span>
    </span>
</footer>
    <script src="/bundle/index.min.js"></script>
    <script src="https://cdn.staticfile.org/prism/1.16.0/prism.min.js"></script>
    <script>
        new Valine({el: '#comment',appId: 'PieJ3iHvVTJ9C5yBudK6sxaT-MdYXbMMI',appKey: 'Yt25unM4vc9wzBvC2lL20Frc',placeholder: 'ヾﾉ≧∀≦)o来啊, 快活啊, 反正有大把时光!!',path: window.location.pathname,avatar: 'retro',pageSize: 10,guest_info: ['nick', 'mail'],lang: 'en'});
    </script>
</body>

</html>